﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Threading;

namespace Quick.CodeGenerator.Generator
{
    /// <summary>
    /// 处理模版
    /// </summary>
    public class Process
    {
        private static Process instance;
        private static object syncRoot = new Object();
        private Process() { }
        /// <summary>
        /// Process  Data
        /// </summary>
        public static Process Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                        {
                            instance = new Process();
                        }
                    }
                }
                return instance;
            }
        }
        private void PostAction(string msg, double percent ,Action<string, double> action = null)
        {
            if (null != action)
            {
                action.BeginInvoke(msg, percent, null, null);
            }
        }
        /// <summary>
        /// 开始执行模版生成程序
        /// </summary>
        /// <param name="setting"></param>
        /// <returns></returns>
        public void Execute(Model.CodeGeneratorSetting pSetting,Data.IDataBase pIDb,Action<string, double> pAction=null)
        {
            Action<Model.CodeGeneratorSetting,Data.IDataBase,Action<string, double>> ac =(setting,iDb,action) =>
            {
                CodeTemplate.ITemplate iTemplate = null;

                //通过设定,获取要抛送的 table 列表 ,以及 table column栏位
                for (int i = 0; i < setting.TableNames.Count; i++)
                {
                    string tbName = setting.TableNames[i];
                    double percent = Math.Round(i / Convert.ToDouble(setting.TableNames.Count) * 100, 2);
                    PostAction($"开始处理实例: {tbName} ", percent, action);
                    var columns = iDb.GetColumnInfoList(tbName);
                    string path = string.Empty;
                    if (setting.HasEntityNamespace)
                    {//Entity 模版生成
                        path = CreateDirectory(setting.SavePath, setting.Project+"."+ setting.EntityNamespace.Replace('.', '\\'));
                        iTemplate = new CodeTemplate.EntityTemplate();
                        string strCode = iTemplate.GenerateTemplate(setting, tbName, columns);
                        //写文件
                        File.WriteAllText(Path.Combine(path, tbName + ".cs"), strCode, Encoding.UTF8);
                        PostAction($"生成:{tbName} Model 文件成功!", percent, action);
                    }
                    if (setting.HasContractsNamespace)
                    {//IData 模版生成
                        path = CreateDirectory(setting.SavePath, setting.Project + "." + setting.ContractsNamespace.Replace('.', '\\'));
                        iTemplate = new CodeTemplate.ContractsTemplate();
                        string strCode = iTemplate.GenerateTemplate(setting, tbName, columns);
                        //写文件
                        File.WriteAllText(Path.Combine(path, "I" + tbName + "Repository.cs"), strCode, Encoding.UTF8);
                        PostAction($"生成:{tbName} IData 文件成功!", percent, action);
                    }
                    if (setting.HasRepositoryNamespace)
                    {//Data 模版生成
                        path = CreateDirectory(setting.SavePath, setting.Project + "." + setting.RepositoryNamespace.Replace('.', '\\'));
                        iTemplate = new CodeTemplate.RepositoriesTemplate();
                        string strCode = iTemplate.GenerateTemplate(setting, tbName, columns);
                        //写文件
                        File.WriteAllText(Path.Combine(path, tbName + "Repository.cs"), strCode, Encoding.UTF8);
                        PostAction($"生成:{tbName} Data 文件成功!", percent, action);
                    }
                    if (setting.HasIDomainNamespace)
                    {//IServices 模版生成
                        path = CreateDirectory(setting.SavePath, setting.Project + "." + setting.IDomainNamespace.Replace('.', '\\') + "\\CodeGenerator");
                        iTemplate = new CodeTemplate.IDomainTemplate();
                        string strCode = iTemplate.GenerateTemplate(setting, tbName, columns);
                        //写文件
                        File.WriteAllText(Path.Combine(path, "I" + tbName + ".cs"), strCode, Encoding.UTF8);
                        PostAction($"生成:{tbName} IServices 文件成功!", percent, action);


                        path = CreateDirectory(setting.SavePath, setting.Project + "." + setting.IDomainNamespace.Replace('.', '\\'));
                        iTemplate = new CodeTemplate.ICustomDomainTemplate();
                        strCode = iTemplate.GenerateTemplate(setting, tbName, columns);
                        //写文件
                        File.WriteAllText(Path.Combine(path, "I" + tbName + ".cs"), strCode, Encoding.UTF8);
                        PostAction($"生成:{tbName} IServices 文件成功!", percent, action);
                    }
                    if (setting.HasDomainNamespace)
                    {//Services 模版生成
                        path = CreateDirectory(setting.SavePath, setting.Project + "." + setting.DomainNamespace.Replace('.', '\\') + "\\CodeGenerator");
                        iTemplate = new CodeTemplate.DomainTemplate();
                        string strCode = iTemplate.GenerateTemplate(setting, tbName, columns);
                        //写文件
                        File.WriteAllText(Path.Combine(path, tbName + ".cs"), strCode, Encoding.UTF8);
                        PostAction($"生成:{tbName} Services 文件成功!", percent, action);

                        path = CreateDirectory(setting.SavePath, setting.Project + "." + setting.DomainNamespace.Replace('.', '\\'));
                        iTemplate = new CodeTemplate.CustomDomainTemplate();
                        strCode = iTemplate.GenerateTemplate(setting, tbName, columns);
                        //写文件
                        File.WriteAllText(Path.Combine(path, tbName + ".cs"), strCode, Encoding.UTF8);
                        PostAction($"生成:{tbName} Services 文件成功!", percent, action);
                    }
                }
                Thread.Sleep(500);
                PostAction("文件处理完毕!", 100, action);
                GC.Collect();
            };
            ac.BeginInvoke(pSetting, pIDb, pAction, null, null);
        }
        /// <summary>
        /// 开始执行模版生成程序
        /// </summary>
        /// <param name="setting"></param>
        /// <param name="pTableName">创建指定的表</param>
        /// <returns></returns>
        public void Execute2String(Model.CodeGeneratorSetting pSetting, Data.IDataBase pIDb,string pTableName ,Action<Model.CodeTemplateString> callBackAction = null)
        {
            Action<Model.CodeGeneratorSetting, Data.IDataBase,string , Action<Model.CodeTemplateString>> ac = (setting, iDb, tbName ,action) =>
            {
                Model.CodeTemplateString cts = new Model.CodeTemplateString();
                CodeTemplate.ITemplate iTemplate = null;
                var columns = iDb.GetColumnInfoList(tbName);
                string path = string.Empty;
                if (setting.HasEntityNamespace)
                {//Model 模版生成
                    path = CreateDirectory(setting.SavePath, setting.EntityNamespace.Replace('.', '\\'));
                    iTemplate = new CodeTemplate.EntityTemplate();
                    cts.ModelTemplateString = iTemplate.GenerateTemplate(setting, tbName, columns);
                }
                if (setting.HasContractsNamespace)
                {//IData 模版生成
                    path = CreateDirectory(setting.SavePath, setting.ContractsNamespace.Replace('.', '\\'));
                    iTemplate = new CodeTemplate.ContractsTemplate();
                    cts.IDataTemplateString = iTemplate.GenerateTemplate(setting, tbName, columns);
                }
                if (setting.HasRepositoryNamespace)
                {//Data 模版生成
                    path = CreateDirectory(setting.SavePath, setting.RepositoryNamespace.Replace('.', '\\'));
                    iTemplate = new CodeTemplate.RepositoriesTemplate();
                    cts.DataTemplateString = iTemplate.GenerateTemplate(setting, tbName, columns);
                }
                if (setting.HasIDomainNamespace)
                {//IServices 模版生成
                    path = CreateDirectory(setting.SavePath, setting.IDomainNamespace.Replace('.', '\\'));
                    iTemplate = new CodeTemplate.IDomainTemplate();
                    cts.IServicesTemplateString = iTemplate.GenerateTemplate(setting, tbName, columns);
                }
                if (setting.HasDomainNamespace)
                {//Services 模版生成
                    path = CreateDirectory(setting.SavePath, setting.DomainNamespace.Replace('.', '\\'));
                    iTemplate = new CodeTemplate.DomainTemplate();
                    cts.ServicesTemplateString = iTemplate.GenerateTemplate(setting, tbName, columns);
                }
                // VueJson 模板生成
                {
                    iTemplate = new CodeTemplate.VueFormTemplate();
                    cts.VueJsonTemplateString = iTemplate.GenerateTemplate(setting, tbName, columns);
                }
                //Db2Model 模板生成
                {
                    iTemplate = new CodeTemplate.DB2Model();
                    cts.Db2ModelTemplateString = iTemplate.GenerateTemplate(setting, tbName, columns);
                }
                action.BeginInvoke(cts, null, null);
                GC.Collect();
            };
            ac.BeginInvoke(pSetting, pIDb, pTableName, callBackAction, null, null);
        }
        /// <summary>
        /// 创建文件目录
        /// </summary>
        /// <param name="path1"></param>
        /// <param name="path2"></param>
        private string CreateDirectory(string path1,string path2)
        {
            string path = Path.Combine(path1.Trim(new char[] { '\\', '/' }), path2.Trim(new char[] { '\\', '/' }));
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            return path;
        }
    }
}
